home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 11.9 KB | 400 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWLink.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFrameW.hpp"
-
- #ifndef FWLINK_H
- #include "FWLink.h"
- #endif
-
- // ----- Framework Includes -----
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWPRESEN_H
- #include "FWPresen.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- // ----- Foundation Includes -----
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODLink_xh
- #include <Link.xh>
- #endif
-
- #ifndef SOM_ODLinkSpec_xh
- #include <LinkSpec.xh>
- #endif
-
- #ifndef SOM_ODLinkSource_xh
- #include <LinkSrc.xh>
- #endif
-
- //========================================================================================
- // Runtime information
- //========================================================================================
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment framework
- #endif
-
- FW_DEFINE_CLASS_M0(FW_CPublishLink)
- FW_DEFINE_CLASS_M0(FW_CSubscribeLink)
-
- //========================================================================================
- // class FW_CPublishLink
- //========================================================================================
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::FW_CPublishLink
- //---------------------------------------------------------------------------------------
-
- FW_CPublishLink::FW_CPublishLink(Environment* ev,
- ODUpdateID updateID,
- FW_CPresentation* presentation)
- {
- fODLinkSource = NULL;
- fUpdateID = updateID;
- fPresentation = presentation;
- fPendingID = updateID;
- fSelected = FALSE;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::SetODLinkSource
- //---------------------------------------------------------------------------------------
-
- void FW_CPublishLink::SetODLinkSource(Environment* ev, ODLinkSource* odLinkSource)
- {
- FW_ASSERT(odLinkSource!=NULL);
- FW_ASSERT(fODLinkSource==NULL);
-
- fODLinkSource = odLinkSource;
- odLinkSource->Acquire(ev);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::~FW_CPublishLink
- //---------------------------------------------------------------------------------------
-
- FW_CPublishLink::~FW_CPublishLink()
- {
- if (fODLinkSource)
- fODLinkSource->Release(somGetGlobalEnvironment());
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::ContentUpdated
- //---------------------------------------------------------------------------------------
-
- void FW_CPublishLink::ContentUpdated(Environment* ev, ODUpdateID updateID,
- FW_Boolean forceUpdate)
- {
- fUpdateID = updateID ? updateID : fPresentation->GetPart(ev)->GetSession(ev)->UniqueUpdateID(ev);
-
- // Don't update unless we really have to
- if (this->IsOKtoUpdate(ev, forceUpdate))
- {
- ODLinkKey key;
- FW_VOLATILE(key);
-
- if (fODLinkSource->Lock(ev, 0, &key))
- {
- FW_TRY
- {
- fODLinkSource->Clear(ev, fUpdateID, key);
- // Clear must be followed by GetContentStorageUnit, which writes out a new set of promises
- ODStorageUnit* linkSU = fODLinkSource->GetContentStorageUnit(ev, key);
-
- ExternalizeLinkContent(ev, linkSU);
-
- if (updateID != kODUnknownUpdate)
- fODLinkSource->ContentUpdated(ev, fUpdateID, key);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- fODLinkSource->Unlock(ev, key);
- FW_THROW_SAME();
- }
- FW_CATCH_END
-
- fODLinkSource->Unlock(ev, key);
- }
- }
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::GetPublishFormat
- //----------------------------------------------------------------------------------------
- ODValueType FW_CPublishLink::GetPublishFormat(Environment* ev)
- {
- // Default to the part's kind
- return fPresentation->GetPart(ev)->GetPartKind(ev);
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::IsOKtoUpdate
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_CPublishLink::IsOKtoUpdate(Environment* ev, FW_Boolean forceUpdate)
- {
- return (forceUpdate || fODLinkSource->IsAutoUpdate(ev));
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::BreakLink
- //----------------------------------------------------------------------------------------
- void FW_CPublishLink::BreakLink(Environment* ev)
- {
- fODLinkSource->SetSourcePart(ev, (ODStorageUnit*) kODNULL);
- fUpdateID = kODUnknownUpdate;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CPublishLink::RestoreLink
- //----------------------------------------------------------------------------------------
- void FW_CPublishLink::RestoreLink(Environment* ev, FW_CPart* part)
- {
- fODLinkSource->SetSourcePart(ev, part->GetStorageUnit(ev));
- }
-
- //========================================================================================
- // class FW_CSubscribeLink
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::FW_CSubscribeLink
- //----------------------------------------------------------------------------------------
-
- FW_CSubscribeLink::FW_CSubscribeLink(Environment* ev,
- ODLink* odLink,
- ODLinkInfo* linkInfo,
- FW_CPresentation* presentation) :
- fODLink(NULL),
- fPresentation(presentation),
- fRegistered(FALSE),
- fSelected(FALSE),
- fPart(NULL),
- fNeedsSubscribe(TRUE)
- {
- if (odLink)
- {
- fODLink = odLink;
- odLink->Acquire(ev);
- }
-
- // Copy link info
- fLinkInfo = *linkInfo;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::~FW_CSubscribeLink
- //----------------------------------------------------------------------------------------
-
- FW_CSubscribeLink::~FW_CSubscribeLink()
- {
- Environment* ev = somGetGlobalEnvironment();
- this->Unregister(ev);
- if (fODLink)
- fODLink->Release(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::HandleSubscribe
- //----------------------------------------------------------------------------------------
-
- void FW_CSubscribeLink::HandleSubscribe(Environment* ev)
- {
- this->Subscribe(ev);
- fNeedsSubscribe = FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::LinkUpdated
- //----------------------------------------------------------------------------------------
-
- void FW_CSubscribeLink::LinkUpdated(Environment* ev, ODUpdateID id)
- {
- ODLinkKey linkKey;
- FW_VOLATILE(linkKey);
-
- /* The following is a kludge to detect when OpenDoc throws an exception in GetContentStorageUnit.
- If a cross-document link was just created, LinkUpdated gets called before the link content SU
- has received any data. In that case we want to just let the exception fall on the floor.
- LinkUpdated will be called again after the link data has been written.
- */
- FW_Boolean linkContentsOK = FALSE;
- FW_VOLATILE(linkContentsOK);
-
- if (fODLink->Lock(ev, 0, &linkKey))
- {
- FW_TRY
- {
- ODStorageUnit* su = fODLink->GetContentStorageUnit(ev, linkKey); /* cross-doc link will fail the 1st time */
- linkContentsOK = TRUE; /* it's safe to update */
- this->DoUpdateLink(ev, su);
-
- // --- Update the link info ---
- fLinkInfo.change = id;
- fLinkInfo.changeTime = fODLink->GetChangeTime(ev);
-
- fODLink->Unlock(ev, linkKey);
-
- if (fNeedsSubscribe) /* first update must have failed */
- this->HandleSubscribe(ev);
-
- // --- Propagate changes to source links maintained by the part ---
- this->DoPropagateChanges(ev, id);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- fODLink->Unlock(ev, linkKey);
- if (linkContentsOK) /* exception was not thrown by GetContentStorageUnit */
- FW_THROW_SAME();
- }
- FW_CATCH_END
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::DoPropagateChanges
- //----------------------------------------------------------------------------------------
- void FW_CSubscribeLink::DoPropagateChanges(Environment* ev, ODUpdateID change)
- {
- FW_CPresentationFrameIterator fiter(fPresentation);
- FW_CFrame* frame = fiter.First();
- fPresentation->GetPart(ev)->ContentUpdated(ev, frame, change);
-
- fPresentation->Invalidate(ev); // force all frames to be redrawn
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::Register
- //----------------------------------------------------------------------------------------
- void FW_CSubscribeLink::Register(Environment* ev, FW_CPart* itsPart)
- {
- ODUpdateID linkUpdateID = fODLink->GetUpdateID(ev);
- FW_Boolean needsUpdate = (fLinkInfo.change != linkUpdateID);
-
- if (fLinkInfo.autoUpdate)
- {
- //--- Register for automatic updates ---
- // First determine if another subscriber with the same ODLink as ours already registered
- FW_Boolean alreadyRegistered = FALSE;
- FW_CPartSubscribeIterator iter(itsPart);
- for (FW_CSubscribeLink* subscriber = iter.First(); iter.IsNotComplete(); subscriber = iter.Next())
- {
- if ((subscriber != this) && fODLink->IsEqualTo(ev, subscriber->GetODLink(ev))
- && subscriber->IsRegistered(ev))
- {
- alreadyRegistered = TRUE;
- break;
- }
- }
- if (!alreadyRegistered)
- {
- fODLink->RegisterDependent(ev, itsPart->GetODPart(ev), fLinkInfo.change);
- // part::LinkUpdated call will be generated
- needsUpdate = FALSE;
- }
- fRegistered = TRUE;
- itsPart->GetODPart(ev)->Acquire(ev);
- fPart = itsPart; // remember which part we're registered to, so we can Unregister
- }
-
- if (needsUpdate) // Manually update now
- this->LinkUpdated(ev, linkUpdateID);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CSubscribeLink::Unregister
- //----------------------------------------------------------------------------------------
- void FW_CSubscribeLink::Unregister(Environment* ev)
- {
- if (!fRegistered) return;
-
- if (fLinkInfo.autoUpdate)
- {
- // Unregister, if this is the last automatically updated destination of the link in the part
- FW_ASSERT(fPart);
- short autoCount = 0;
- FW_CPartSubscribeIterator iter(fPart);
- for (FW_CSubscribeLink* subscriber = iter.First(); iter.IsNotComplete(); subscriber = iter.Next())
- {
- if (subscriber->IsAutoUpdate(ev) && fODLink->IsEqualTo(ev, subscriber->GetODLink(ev)))
- autoCount++;
- }
- if (autoCount == 1) // this is the only registered link
- {
- fODLink->UnregisterDependent(ev, fPart->GetODPart(ev));
- }
- }
-
- if (fPart)
- {
- fPart->GetODPart(ev)->Release(ev);
- fPart = NULL;
- }
-
- fRegistered = FALSE;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CSubscribeLink::BreakLink
- //----------------------------------------------------------------------------------------
- void FW_CSubscribeLink::BreakLink(Environment* ev)
- {
- this->Unregister(ev);
- fNeedsSubscribe = TRUE;
- }
-
- //---------------------------------------------------------------------------------------
- // FW_CSubscribeLink::RestoreLink
- //----------------------------------------------------------------------------------------
- void FW_CSubscribeLink::RestoreLink(Environment* ev, FW_CPart* part)
- {
- fLinkInfo.change = kODUnknownUpdate;
-
- // Re-register the link if necessary
- this->Register(ev, part);
- }
-
-